home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
398
/
398.xpi
/
chrome
/
forecastfox.jar
/
content
/
icons
/
pack-service.js
< prev
next >
Wrap
Text File
|
2010-02-04
|
36KB
|
1,242 lines
/*------------------------------------------------------------------------------
Copyright (c) 2008 Ensolis, LLC. All Rights Reserved.
----------------------------------------------------------------------------*/
/******************************************************************************
* DTD and Namespace Constants for icons.xml
*****************************************************************************/
const ICONS_DTD = "http://forecastfox.ensolis.com/specs/1.0/icons.dtd";
const ICONS_NS = "http://forecastfox.ensolis.com/specs/1.0/icons";
/******************************************************************************
* Icon Pack Constants
*****************************************************************************/
const PACK_ROOT = "http://www.ensolis.com/2005/icon-pack/install";
const PACK_PREFIX = "http://www.ensolis.com/2005/icon-manager#";
const PACK_PROPERTIES = ["id", "name", "version", "website", "author",
"target", "smallWidth", "smallHeight", "largeWidth",
"largeHeight"];
const PACK_FILES = ["pack.rdf", "small/01.png", "small/02.png", "small/03.png",
"small/04.png", "small/05.png", "small/06.png",
"small/07.png", "small/08.png", "small/11.png",
"small/12.png", "small/13.png", "small/14.png",
"small/15.png", "small/16.png", "small/17.png",
"small/18.png", "small/19.png", "small/20.png",
"small/21.png", "small/22.png", "small/23.png",
"small/24.png", "small/25.png", "small/26.png",
"small/29.png", "small/30.png", "small/31.png",
"small/32.png", "small/33.png", "small/34.png",
"small/35.png", "small/36.png", "small/37.png",
"small/38.png", "small/39.png", "small/40.png",
"small/41.png", "small/42.png", "small/43.png",
"small/44.png", "small/radar.png", "small/swa.png",
"large/01.png", "large/02.png", "large/03.png",
"large/04.png", "large/05.png", "large/06.png",
"large/07.png", "large/08.png", "large/11.png",
"large/12.png", "large/13.png", "large/14.png",
"large/15.png", "large/16.png", "large/17.png",
"large/18.png", "large/19.png", "large/20.png",
"large/21.png", "large/22.png", "large/23.png",
"large/24.png", "large/25.png", "large/26.png",
"large/29.png", "large/30.png", "large/31.png",
"large/32.png", "large/33.png", "large/34.png",
"large/35.png", "large/36.png", "large/37.png",
"large/38.png", "large/39.png", "large/40.png",
"large/41.png", "large/42.png", "large/43.png",
"large/44.png", "large/swa.png"];
/******************************************************************************
* Reads an icon pack file from disk validates the pack has the required
* files and properties and creates a icon pack item. If the pack file is not
* valid then a error item is created.
* This implements the nsIRunnable interface so it could
* be dispatched to a thread.
*
* @param File to read.
* @return An ffIPackItem if the file is valid, otherwise a ffIErrorItem is
* returned. Callers should check the instanceof to determine.
*****************************************************************************/
function PackReader(aFile)
{
this.file = aFile;
}
PackReader.prototype = {
_file: null,
_item: null,
_dskSvc: null,
_rdfSvc: null,
_temp: null,
_bundle: null,
get file() { return this._file; },
set file(aVal) { this._file = aVal; },
get item() { return this._item; },
set item(aVal) { this._item = aVal; },
get bundle() { return this._bundle; },
///////////////////////////
// nsISupports
QueryInterface: function PackReader_QueryInterface(aIID)
{
if (!aIID.equals(Ci.nsIRunnable) &&
!aIID.equals(Ci.nsISupports))
throw Components.results.NS_ERROR_NO_INTERFACE;
return this;
},
///////////////////////////
// nsIRunnable
run: function PackReader_run()
{
//initialize the needed variables
this._init();
//open the zip file
var reader = Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(Ci.nsIZipReader);
try {
//toolkit 2.0 and prior or non toolkit
if ("init" in reader) {
reader.init(this.file);
reader.open();
//toolkit 3.0
} else
reader.open(this.file);
//error opening the zip file
} catch(e) {
this._setError("open", this.file.path);
this._destroy(reader);
return;
}
//get the zip entries
var entries = this._getEntries(reader);
//check the entries are valid
if (!this._checkEntries(entries)) {
this._destroy(reader);
return;
}
//get the install manifest
var manifest = this._getManifest(reader);
//check the manifest is valid
if (!this._checkManifest(manifest)) {
this._destroy(reader);
return;
}
//create the pack item
this._item = this._createItem(manifest);
//cleanup and return
this._destroy(reader);
return;
},
/**
* Initialize internal variables.
*/
_init: function PackReader__init()
{
//get the stringbundle
this._bundle = getBundle();
//get the disk service
var mgrSvc = Cc["@ensolis.com/forecastfox/manager-service;1"].
getService(Ci.ffIManagerService);
this._dskSvc = mgrSvc.disk;
//get the rdf service
this._rdfSvc = Cc["@mozilla.org/rdf/rdf-service;1"].
getService(Ci.nsIRDFService);
//get a temp file for the install manifest
this._temp = this._dskSvc.get("icon-pack.rdf", TYPE_TEMP);
},
/**
* cleanup internal variables and close the zip reader.
*
* @param The zip reader.
*/
_destroy: function PackReader__destroy(aReader)
{
//close the reader
try {
aReader.close();
} catch(e) {}
//remove the temp file
try {
removeFile(this._temp);
} catch(e) {}
//clear variables
this._dskSvc = null;
this._rdfSvc = null;
this._temp = null;
this._bundle = null;
},
_setError: function PackReader__setError(aType, aData)
{
//get the error name and message
const PREFIX = "ff.packs.read.";
var name = this.bundle.GetStringFromName(PREFIX + "name");
var message = this.bundle.formatStringFromName(PREFIX + aType + ".message",
[aData], 1);
//create an error item
this._item = Cc["@ensolis.com/forecastfox/error-item;1"].
createInstance(Ci.ffIErrorItem);
//set the error
this._item.init(SEVERITY_ERROR, name, message);
},
/**
* Get the entries in the zip file.
*
* @param The zip reader.
* @return An object containing the entries.
*/
_getEntries: function PackReader__getEntries(aReader)
{
var rv = {};
//loop through the entries
var entries = aReader.findEntries("*");
var entry = null;
//toolkit 2.0 and prior or non toolkit
if ("hasMoreElements" in entries) {
while (entries.hasMoreElements()) {
entry = entries.getNext().QueryInterface(Ci.nsIZipEntry);
rv[entry.name] = entry.name;
}
//toolkit 3.0
} else {
while (entries.hasMore()) {
entry = entries.getNext();
rv[entry] = entry;
}
}
//return the object
return rv;
},
/**
* Check that all the required entries exist.
*
* @param An object containing the entries.
* @return False if an entry is missing.
*/
_checkEntries: function PackReader__checkEntries(aEntries)
{
//loop through required files
for (var i=0; i<PACK_FILES.length; i++) {
var file = PACK_FILES[i];
//missing an entry
if (!aEntries.hasOwnProperty(file)) {
this._setError("entry", file);
return false;
}
}
//all entries exist
return true;
},
/**
* Extract the manifest file to a temp file and
* load it into an RDF datasource.
*
* @param The zip reader.
* @return The manifest file.
*/
_getManifest: function PackReader__getManifest(aReader)
{
//extract the file
aReader.extract("pack.rdf", this._temp);
//load the datasource
var URL = this._dskSvc.getFileURL(this._temp);
return this._rdfSvc.GetDataSourceBlocking(URL);
},
/**
* Check that all the required properties exist in the manifest.
*
* @param The manifest datasource.
* @return False if a property is missing.
*/
_checkManifest: function PackReader__checkManifest(aManifest)
{
//get the root resource
var root = this._rdfSvc.GetResource(PACK_ROOT);
//check for the required properties
for (var i=0; i<PACK_PROPERTIES.length; i++) {
var property = PACK_PROPERTIES[i];
//get the property resource
var resource = this._rdfSvc.GetResource(PACK_PREFIX + property);
//resource is missing
if (!aManifest.hasArcOut(root, resource)) {
this._setError("manifest", property);
this._rdfSvc.UnregisterDataSource(aManifest);
return false;
}
}
//all properties exist
return true;
},
/**
* Create an icon pack from the pack manifest.
*
* @param The manifest datasource.
* @return An ffIPackItem object.
*/
_createItem: function PackReader__createItem(aManifest)
{
//create an empty pack item
var pack = Cc["@ensolis.com/forecastfox/pack-item;1"].
createInstance(Ci.ffIPackItem);
//get the root resource
var root = this._rdfSvc.GetResource(PACK_ROOT);
//copy the required properties.
for (var i=0; i<PACK_PROPERTIES.length; ++i) {
var property = PACK_PROPERTIES[i];
//get the property resource
var resource = this._rdfSvc.GetResource(PACK_PREFIX + property);
//set the pack property
var value = this._evalResource(aManifest, root, resource);
if (property == "id")
pack.setProperty("ID", value);
else
pack.setProperty(property, value);
}
//loop through exemptions
resource = this._rdfSvc.GetResource(PACK_PREFIX + "exemption");
var targets = aManifest.GetTargets(root, resource, true);
while (targets.hasMoreElements()) {
var target = targets.getNext().QueryInterface(Ci.nsIRDFResource);
//create an empty icon item
var icon = Cc["@ensolis.com/forecastfox/icon-item;1"].
createInstance(Ci.ffIIconItem);
//get the exemption resources
var index = this._rdfSvc.GetResource(PACK_PREFIX + "index");
var size = this._rdfSvc.GetResource(PACK_PREFIX + "size");
var width = this._rdfSvc.GetResource(PACK_PREFIX + "width");
var height = this._rdfSvc.GetResource(PACK_PREFIX + "height");
//set the values
icon.setProperty("index", this._evalResource(aManifest, target, index));
icon.setProperty("size", this._evalResource(aManifest, target, size));
icon.setProperty("width", this._evalResource(aManifest, target, width));
icon.setProperty("height", this._evalResource(aManifest, target, height));
icon.setProperty("isExemption", true);
//add the icon to the pack
pack.setItem(icon);
}
//unregister the datasource
this._rdfSvc.UnregisterDataSource(aManifest);
//return the pack item
return pack;
},
/**
* Evaluate an RDF resource and return its value.
*
* @param The manifest datasource.
* @param The root resource.
* @param The target resource.
* @return The value of the target.
*/
_evalResource: function PackReader__evalResource(aManifest, aRoot, aResource)
{
//get the target resource
var target = aManifest.GetTarget(aRoot, aResource, true);
//return the targets value
if (target instanceof Ci.nsIRDFLiteral)
return target.Value;
if (target instanceof Ci.nsIRDFResource)
return target.Value;
if (target instanceof Ci.nsIRDFInt)
return target.Value;
return "undefined";
}
};
/******************************************************************************
* Interface for describing the icon pack service. This service should
* be used for all profile data related changes.
*
* @status FROZEN
* @version 1.0
******************************************************************************/
function PackService()
{
//setup additional interfaces
this._ifaces.push(Ci.nsIObserver);
this._ifaces.push(Ci.nsISupportsWeakReference);
//setup a new error
this._error = Cc["@ensolis.com/forecastfox/error-item;1"].
createInstance(Ci.ffIErrorItem);
}
PackService.prototype = {
__proto__: new ServiceBase("PackService"),
_dskSvc: null,
_obSvc: null,
_items: null,
_isBatch: null,
_isLoading: null,
_flushPending: null,
///////////////////////////
// nsIObserver
observe: function PackService_observe(aSubject, aTopic, aData)
{
switch (aTopic) {
//preference change
case "nsPref:changed":
//ignore changes if we are loading
if (this.isLoading)
return;
//current changed
this.current = this.getItem(getPref(aData));
break;
}
},
////////////////////////////////
// ffIService
/**
* Initialize the component. Called by the manager service. Returns false
* if the datasource could not be loaded. Chech the lastError property for
* more information.
*/
start: function PackService_start()
{
//setup the variables
this._items = {};
this._isBatch = false;
this._isLoading = false;
this._flushPending = false;
//get the disk service
var mgrSvc = Cc["@ensolis.com/forecastfox/manager-service;1"].
getService(Ci.ffIManagerService);
this._dskSvc = mgrSvc.disk;
//get the observer service
this._obSvc = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
//start batch mode
this.startBatch();
//remove old files
this._removeFiles(null);
//load icon packs
var success = this._loadPacks();
//end batch mode
this.endBatch();
//setup a preference observer
var pb2 = this.branch.QueryInterface(Ci.nsIPrefBranchInternal);
pb2.addObserver("icons.current", this, true);
//return our success code
return success;
},
/**
* Destroy the component. Called by the manager service. This may be
* called prior to start so it needs to be safe.
*/
stop: function PackService_stop()
{
//remove the pref observer
var pb2 = this.branch.QueryInterface(Ci.nsIPrefBranchInternal);
pb2.removeObserver("icons.current", this);
//clear variables
this._dskSvc = null;
this._obSvc = null;
this._items = null;
this._isBatch = null;
this._isLoading = null;
this._flushPending = null;
},
////////////////////////////////
// ffIPackService
/**
* Currently selected pack item.
*/
get current() { return this._ensureItem(); },
set current(aVal) {
//do nothing if null passed in
if (!aVal)
return;
//do nothing if we don't have it
if (!this.hasItem(aVal.ID))
return;
//load the items properties
this._items[aVal.ID] = aVal.clone();
this._loadItem(aVal);
//notify observers
this._obSvc.notifyObservers(aVal, "forecastfox-icons", "current");
},
/**
* Pack service is in batch mode.
*/
get isBatch() { return this._isBatch; },
/**
* Icon pack is being loaded into preferences.
*/
get isLoading() { return this._isLoading; },
/**
* Pack service has a specific item.
*
* @param ID of the pack item.
* @return True if item exists.
*/
hasItem: function PackService_hasItem(aID)
{
return this._items.hasOwnProperty(aID);
},
/**
* Retrieve a pack item returns null if item doesn't exist.
*
* @param ID of the pack item.
* @return A ffIPackItem.
*/
getItem: function PackService_getItem(aID)
{
if (!this.hasItem(aID))
return null;
else
return this._items[aID];
},
/**
* Retrieve an array of pack items.
*
* @param Count of items in the array.
* @return An array of ffIPackItem components.
*/
getItems: function PackService_getItems(aCount)
{
//loop through items
var items = [];
for (var id in this._items)
items.push(this._items[id]);
//sort the array
items.sort(sortByName);
//return the array
aCount.value = items.length;
return items;
},
/**
* Sets a pack item. Returns false if pack could not be set.
* Use the lastError property for more information.
*
* @param The icon pack file.
* @return False if pack could not be set.
*/
setItem: function PackService_setItem(aFile)
{
//setup error variables
const PREFIX = "ff.packs.set.";
var name = this.bundle.GetStringFromName(PREFIX + "name");
var message = "";
//error if the file does not exists
if (!aFile.exists()) {
message = this.bundle.GetStringFromName(PREFIX + "exist.message");
this._error.init(SEVERITY_ERROR, name, message);
return false;
}
//error if the file is not readable
if (!aFile.isReadable()) {
message = this.bundle.formatStringFromName(PREFIX + "read.message",
[aFile.path], 1);
this._error.init(SEVERITY_ERROR, name, message);
return false;
}
//error if the file is not a jar
if (!aFile.leafName.match(".jar")) {
message = this.bundle.GetStringFromName(PREFIX + "jar.message");
this._error.init(SEVERITY_ERROR, name, message);
return false;
}
//read the pack
var reader = new PackReader(aFile);
reader.run();
var item = reader.item;
//check if the item is an error
if (item instanceof Ci.ffIErrorItem) {
this._error.init(item.severity, name, item.message);
return false;
}
//copy the file to the icon directory
var file = this._dskSvc.get(aFile.leafName, TYPE_ICONS);
file.createUnique(file.NORMAL_FILE_TYPE, PERMS_FILE);
try {
this._dskSvc.copy(aFile, file);
} catch(e) {
this._error.init(SEVERITY_ERROR, name, e.message);
return false;
}
//remove the item if it is currently installed
var success = true;
if (this.hasItem(item.ID))
success = this.deleteItem(item.ID);
//check if delete was successful
if (!success) {
try {
removeFile(file);
} catch(e) {}
var err = this.lastError;
this._error.init(err.severity, name, err.message);
return false;
}
//set the jar property
item.setProperty("jar", file.leafName);
//save the item
this._items[item.ID] = item;
//flush async
this._flushData();
//notify observers
this._obSvc.notifyObservers(this, "forecastfox-icons", "setItem");
//return successful
return true;
},
/**
* Remove a pack item. It also removes that pack file.
* Use the lastError property for more information.
*
* @param ID of the pack item.
* @return False if pack could not be deleted.
*/
deleteItem: function PackService_deleteItem(aID)
{
//do nothing if we don't have item
if (!this.hasItem(aID))
return false;
//if the item is the current then load the next one
if (!this.isBatch && this.current.ID == aID)
this.current = this._nextItem();
//remove the items file
this._removeFiles(this._items[aID].getProperty("jar"));
//remove the item
delete this._items[aID];
//flush async
this._flushData();
//notify observers
this._obSvc.notifyObservers(this, "forecastfox-icons", "deleteItem");
//return successful
return true;
},
/**
* Turn on batch mode. Observers will get a notification of this.
* They will still get notified for every individual change, but they are
* free to ignore those notifications.
* Use this when a lot of changes are about to happen, and it would be
* useless to refresh the display (or the backend store) for every change.
* Caller must make sure to also call endBatch. Make sure all errors
* are caught!
*/
startBatch: function PackService_startBatch()
{
//do nothing if already batch
if (this.isBatch)
return;
//mark batch
this._isBatch = true;
//notify observers
this._obSvc.notifyObservers(this, "forecastfox-icons", "startBatch");
},
/**
* Turn off batch mode.
*/
endBatch: function PackService_endBatch()
{
//do nothing if not batch
if (!this.isBatch)
return;
//make sure we have the default profile
if (!this.hasItem("default"))
var item = this._getDefaultItem();
//make sure we have a current profile
if (!this.hasItem(getPref("icons.current")))
this.current = item;
//mark not batch
this._isBatch = false;
// flush data if we have pending changes
if (this._flushPending) {
this._flushData();
this._flushPending = false;
}
//notify observers
this._obSvc.notifyObservers(this, "forecastfox-icons", "endBatch");
},
////////////////////////////////
// Internal Functions
/**
* Select the next pack item.
*/
_nextItem: function PackService__nextItem()
{
//setup variables
var ids = [];
var index = 0;
var current = this.current.ID;
var found = false;
//loop through items
for (var id in this._items) {
//mark that we found the current
if (current == id)
found = true;
//increment the index
if (!found)
index++;
//save the id
ids.push(id);
}
//return the next item
index = (index + 1 < ids.length) ? index + 1 : 0;
return this._items[ids[index]];
},
/**
* Load an item into preferences.
*
* @param The item to load.
*/
_loadItem: function PackService__loadItem(aItem)
{
//mark we are loading
this._isLoading = true;
//set the current pref
setPref("icons.current", aItem.ID);
//mark we are finished loading
this._isLoading = false;
},
/**
* Ensure there is an item available for the current property.
*
* @return A profile item.
*/
_ensureItem: function PackService__ensureItem()
{
//get the current item
var item = this.getItem(getPref("icons.current"));
if (!item) {
//get all items
var items = this.getItems({});
//set to the first one
if (items.length > 0)
item = items[0];
//get the default
else
item = this._getDefaultItem();
}
//return the item
return item;
},
/**
* Get the default icon pack item.
*
* @return A ffIPackItem.
*/
_getDefaultItem: function PackService__getDefaultItem()
{
//log that we are installing the default
this._dskSvc.log("Installing the default icon pack.", null, null);
//get the default.jar file
var file = this._dskSvc.get("default.jar", TYPE_DEFAULTS);
//install the item
var success = this.setItem(file);
//install was unsuccessful
var item;
if (!success) {
this._dskSvc.log("Failed to install the default pack because: " +
this.lastError.toString(), null, null);
item = Cc["@ensolis.com/forecastfox/pack-item;1"].
createInstance(Ci.ffIPackItem);
this._items["default"] = item;
this._flushData();
//install was successful
} else
item = this.getItem("default");
//return the item
return item;
},
/**
* Try to remove old icon pack files that are marked for deletion.
*
* @param A file to try removing
*/
_removeFiles: function PackService__removeFiles(aName)
{
//get the names stored in prefs
var names = getPref("icons.uninstallfiles");
if (!aName && names == "")
return;
//split the names into an array and add the passed in name
if (names != "")
names = names.split(";");
else
names = [];
if (aName)
names.push(aName);
//loop through the file names
var dir = this._dskSvc.get("", TYPE_ICONS);
var remaining = [];
for (var i=0; i<names.length; i++) {
var file = dir.clone();
file.append(names[i]);
//skip if file does not exist
if (!file.exists())
continue;
//try to remove the file
try {
removeFile(file);
//save the name since we could not remove it
} catch (e) {
remaining.push(file.leafName);
}
}
//save the remaining files back to prefs
setPref("icons.uninstallfiles", remaining.join(";"));
},
/**
* Create a pack item from a DOM node.
*
* @param The pack DOM node.
* @return A pack item.
*/
_createItem: function PackService__createItem(aNode)
{
//create an empty pack item
var item = Cc["@ensolis.com/forecastfox/pack-item;1"].
createInstance(Ci.ffIPackItem);
//set the name and ID
item.setProperty("name", aNode.getAttribute("name"));
item.setProperty("ID", aNode.getAttribute("id"));
//loop through property nodes
var properties = aNode.getElementsByTagName("properties")[0];
properties = properties.getElementsByTagName("property");
for (var i=0; i<properties.length; i++) {
var property = properties[i];
//get the property node attributes
var name = property.getAttribute("name");
var value = property.getAttribute("value");
var type = property.getAttribute("type");
//set the item property based on type
switch (type) {
case "Int":
item.setProperty(name, Number(value));
break;
case "Bool":
item.setProperty(name, Boolean(value));
break;
case "Char":
default:
item.setProperty(name, value);
break;
}
}
//loop through the exemption nodes
var exemptions = aNode.getElementsByTagName("exemptions")[0];
exemptions = exemptions.getElementsByTagName("exemption");
for (i=0; i<exemptions.length; i++) {
//create an empty icon item
var icon = Cc["@ensolis.com/forecastfox/icon-item;1"].
createInstance(Ci.ffIIconItem);
//loop through property nodes
properties = exemptions[i].getElementsByTagName("property");
for (var j=0; j<properties.length; j++) {
property = properties[j];
//get the property node attributes
name = property.getAttribute("name");
value = property.getAttribute("value");
type = property.getAttribute("type");
//set the icon property based on type
switch (type) {
case "Int":
icon.setProperty(name, Number(value));
break;
case "Bool":
icon.setProperty(name, Boolean(value));
break;
case "Char":
default:
icon.setProperty(name, value);
break;
}
}
//add the icon to the pack
icon.setProperty("isExemption", true);
item.setItem(icon);
}
//return the item
return item;
},
/**
* Create a DOM node from a pack item.
*
* @param The pack item.
* @param The owner document of the node.
* @return The DOM node.
*/
_createNode: function PackService__createNode(aItem, aDoc)
{
//create pack, properties, and exemptions nodes
var pack = aDoc.createElementNS(ICONS_NS, "pack");
var properties = aDoc.createElementNS(ICONS_NS, "properties");
var exemptions = aDoc.createElementNS(ICONS_NS, "exemptions");
//set the name and id
pack.setAttribute("id", aItem.ID);
pack.setAttribute("name", aItem.name);
//loop through the items properties
var props = aItem.properties;
while (props.hasMore()) {
var name = props.getNext();
//skip ID and name properties
if (name == "ID" || name == "name")
continue;
//set the node properties
var node = aDoc.createElementNS(ICONS_NS, "property");
var value = aItem.getProperty(name);
node.setAttribute("name", name);
node.setAttribute("value", String(value));
if (typeof value == "number")
node.setAttribute("type", "Int");
else if (typeof value == "boolean")
node.setAttribute("type", "Bool");
else
node.setAttribute("type", "Char");
//append it to the properties node
properties.appendChild(node);
}
//loop through the packs icon items
var items = aItem.getItems(true, {});
for (var i=0; i<items.length; i++) {
var item = items[i];
//loop through the items properties
var exemption = aDoc.createElementNS(ICONS_NS, "exemption");
props = item.properties;
while (props.hasMore()) {
name = props.getNext();
//skip URL and isExemption
if (name == "URL" || name == "isExemption")
continue;
//set the node properties
node = aDoc.createElementNS(ICONS_NS, "property");
value = item.getProperty(name);
node.setAttribute("name", name);
node.setAttribute("value", String(value));
if (typeof value == "number")
node.setAttribute("type", "Int");
else if (typeof value == "boolean")
node.setAttribute("type", "Bool");
else
node.setAttribute("type", "Char");
//append it to the exemption node
exemption.appendChild(node);
}
//append it to the exemptions node
exemptions.appendChild(exemption);
}
//append properties and exemptions
pack.appendChild(properties);
pack.appendChild(exemptions);
//return the node
return pack;
},
/**
* Flush changes to disk.
*
* @param Call file writer in blocking mode.
*/
_flushData: function PackService__flushData()
{
//do nothing if in batch mode
if (this.isBatch) {
this._flushPending = true;
return;
}
//do nothing if not writable
var file = this._dskSvc.get("icons.xml", TYPE_PROFILE);
if ((!file.exists() && !file.parent.isWritable()) ||
(file.exists() && !file.isWritable())) {
this._dskSvc.log("Icon pack file is not writable: " + file.path,
null, null);
return;
}
//create a new icons document
var doc = this._dskSvc.create("icons", ICONS_DTD, ICONS_NS);
//loop through items
for (var id in this._items) {
var item = this._items[id];
//create the node
var node = this._createNode(item, doc);
//append it to the document
doc.documentElement.appendChild(node);
}
//write to disk
this._dskSvc.write(file, doc, false, false);
},
/**
* Load the icon packs datasource.
*
* @return False if we could not get the packs loaded.
*/
_loadPacks: function PackService__loadPacks()
{
//setup error variables
const PREFIX = "ff.packs.load.";
var name = this.bundle.GetStringFromName(PREFIX + "name");
var message = "";
//get icons.xml
var dir = this._dskSvc.get("", TYPE_ICONS);
var file = this._dskSvc.get("icons.xml", TYPE_PROFILE);
if (file.exists()) {
//file not readable-writable
if (!file.isReadable() || !file.isWritable()) {
message = this.bundle.formatStringFromName(PREFIX + ".perms.message",
[file.path], 1);
this._error.init(SEVERITY_ERROR, name, message);
return false;
}
//read the file into a document
var doc = this._dskSvc.read(file);
//doc not valid
if (!this._dskSvc.validate(doc, "icons")) {
message = this.bundle.GetStringFromName(PREFIX + ".valid.message");
this._error.init(SEVERITY_ERROR, name, message);
return false;
}
//loop through the pack nodes
var isDirty = false;
var nodes = doc.getElementsByTagName("pack");
for (var i=0; i<nodes.length; i++) {
//create an item
var item = this._createItem(nodes[i]);
//make sure the jar file exists
if (!item.hasProperty("jar")) {
isDirty = true;
continue;
} else {
file = dir.clone();
file.append(item.getProperty("jar"));
if (!file.exists()) {
isDirty = true;
continue;
}
}
//save the item
this._items[item.ID] = item;
}
// flush the data if it changed
if (isDirty)
this._flushData();
//icons.xml does not exist
} else {
//log that datasource was missing
this._dskSvc.log("Expected icons.xml, but was missing.", null, null);
//file not readable-writable
if (!file.parent.isReadable() || !file.parent.isWritable()) {
message = this.bundle.formatStringFromName(PREFIX + ".perms.message",
[file.path], 1);
this._error.init(SEVERITY_ERROR, name, message);
return false;
}
//loop through files in the directory
var files = dir.directoryEntries;
var todo = [];
while (files.hasMoreElements()) {
//save the file name to an array
file = files.getNext().QueryInterface(Ci.nsIFile);
if (file.leafName.match(".jar"))
todo.push(file.leafName);
else
this._removeFiles(file.leafName);
}
// loop backward through the array
while(todo.length) {
//install the file
file = this._dskSvc.get(todo.pop(), TYPE_ICONS);
var success = this.setItem(file);
if (!success)
this._dskSvc.log("Failed to install icon pack because: " +
this.lastError.toString(), null, null);
//remove the old file
this._removeFiles(file.leafName);
}
}
//ensure we have the default icon pack
if (!this.hasItem("default"))
this.current = this._getDefaultItem();
//load is successful
return true;
}
};